今天就快速的來幫這遊戲收尾吧,昨天完成的進度到敵人會發射子彈.
那今天要做的事情有兩個,一個是判定玩家被擊中.另一個則是若生命沒了重置遊戲,還有敵人被全滅要重置遊戲.
那就先來寫個重置遊戲
resetGame = () => {
resetEnemy();
chance = 3;
}
先把他加入之前寫的玩家擊中敵人的判定式
// 是否擊中
shootCheck = (x, y) => {
var col = Math.floor ((x - enemy_distance + ENEMY_SPACING_X ) / (ENEMY_R + ENEMY_SPACING_X));
var row = Math.floor (y / (ENEMY_R + ENEMY_SPACING_Y));
var enemyIndex = enemyToIndex(col, row);
if(enemy_grid[enemyIndex] == 1 && col < ENEMY_COLS && col >= 0) {
console.log(x, y, col, row, enemy_distance, enemyIndex);
enemy_grid[enemyIndex] = 0;
player_shot = false;
enemy_left -= 1;
if(enemy_left == 0) {
resetGame();
}
}
}
再來就寫個玩家被擊中的判定式
// 敵人是否擊中
enemyShootCheck = () => {
var distance = Math.sqrt(Math.pow(player_x - enemy_bullet_x, 2) + Math.pow((canvas.height - PLAYER_DIST_FROM_EDGE) - enemy_bullet_y, 2));
if(distance < PLAYER_R) {
chance -= 1;
enemy_shot = false;
if(chance < 0) {
resetGame();
}
}
}
把放入移動子彈的函式中,不斷做檢查
// 移動子彈
moveBullet = () => {
// 玩家發射子彈
if(player_shot) {
bullet_y -= BULLET_SPEED;
//確認子但是否擊中
shootCheck(bullet_x, bullet_y);
// 若子彈超出邊界,重新上膛
if(bullet_y < 0) {
player_shot = false;
}
}
// 敵人發射子彈
if(enemy_shot) {
enemy_bullet_y += BULLET_SPEED;
enemyShootCheck();
// 若子彈超出邊界,重新上膛
if(enemy_bullet_y > canvas.height) {
enemy_shot = false;
}
}
}
OKOK!! 第二個遊戲也算是完成啦. 剩下9天了~~~ 這挑戰有點虐人啊
最後附上第二個遊戲的完整程式碼
<!DOCTYPE html>
<html lang="en">
<head>
<title>Second Game</title>
<meta name="description" content="第一個遊戲">
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
</head>
<body>
<canvas id="playground" width="800" height="630"></canvas>
<script>
// 生命設定
const LIFE_SIZE = 30;
var chance = 3;
// 玩家設定
const PLAYER_DIST_FROM_EDGE = 50;
const PLAYER_R = 15;
var player_x = 400;
// 玩家子彈設定
const BULLET_R = 2.5;
const BULLET_SPEED = 10;
var bullet_x;
var bullet_y;
var player_shot = false;
// 敵人子彈設定
var enemy_bullet_x;
var enemy_bullet_y;
var enemy_shot = false;
// 敵人設定
const ENEMY_R = 20;
const ENEMY_SPACING_X = 30;
const ENEMY_SPACING_Y = 25;
const ENEMY_COLS = 9;
const ENEMY_ROWS = 7;
var enemy_grid = new Array(ENEMY_COLS * ENEMY_ROWS);
var enemy_left = 0;
// 敵人移動設定
var enemy_speed = 3;
var enemy_distance = 3 * ENEMY_R;
window.onload = () => {
canvas = document.getElementById('playground');
canvasContext = canvas.getContext('2d');
//一秒更新幾次畫面
var timesPerSec = 30;
setInterval(drawAll, 1000 / timesPerSec);
// 抓滑鼠位置
canvas.addEventListener('mousemove', mousePos);
// 滑鼠點擊
canvas.addEventListener('mousedown', mouseClick);
// 重置敵人
resetEnemy();
}
// 負責更新畫面
drawAll = () => {
move();
draw();
}
// 負責畫畫
draw = () => {
// background
drawRectangle(0, 0, canvas.width, canvas.height, 'black');
// 畫線
drawLine(0, LIFE_SIZE, canvas.width, LIFE_SIZE, 'white')
// 畫出生命
showLife(chance);
// 畫出玩家
drawCircle(player_x, (canvas.height - PLAYER_DIST_FROM_EDGE), PLAYER_R, 'gray')
// 顯示子彈
showBullet();
// 顯示敵人
showEnemy();
}
// 負責處理動作
move = () => {
// 子彈移動
moveBullet();
// 移動敵人
moveEnemy();
// 敵人發射
enemyShoot();
}
// 顯示子彈
showBullet = () => {
// 如果玩家發射子彈
if(player_shot) {
drawCircle(bullet_x, bullet_y, BULLET_R, '#FF9D6F')
}
// 如果敵人發射子彈
if(enemy_shot) {
drawCircle(enemy_bullet_x, enemy_bullet_y, BULLET_R, '#FF60AF')
}
}
// 玩家發射子彈
playerShoot = () => {
if(player_shot == false) {
bullet_x = player_x;
bullet_y = (canvas.height - PLAYER_DIST_FROM_EDGE - PLAYER_R);
player_shot = true;
}
}
// 敵人發射子彈
enemyShoot = () => {
// 如果已經發射,直接返回
if(enemy_shot) {
return;
}
// 根據玩家位置發射
var col = ( player_x - enemy_distance + ENEMY_SPACING_X) / (ENEMY_R + ENEMY_SPACING_X);
col = Math.floor(col);
if(col < 0 || col >= ENEMY_COLS) {
return;
}
//由最下方敵人發射
for (var row = ENEMY_ROWS - 1; row >= 0; row--) {
var enemyIndex = enemyToIndex(col, row);
if(enemy_grid[enemyIndex] == 1) {
enemy_shot = true;
enemy_bullet_x = col * (ENEMY_R + ENEMY_SPACING_X) + enemy_distance;
enemy_bullet_y = row * (ENEMY_R + ENEMY_SPACING_Y) + ENEMY_R;
return;
}
}
}
// 移動子彈
moveBullet = () => {
// 玩家發射子彈
if(player_shot) {
bullet_y -= BULLET_SPEED;
//確認子但是否擊中
shootCheck(bullet_x, bullet_y);
// 若子彈超出邊界,重新上膛
if(bullet_y < 0) {
player_shot = false;
}
}
// 敵人發射子彈
if(enemy_shot) {
enemy_bullet_y += BULLET_SPEED;
enemyShootCheck();
// 若子彈超出邊界,重新上膛
if(enemy_bullet_y > canvas.height) {
enemy_shot = false;
}
}
}
// 是否擊中
shootCheck = (x, y) => {
var col = Math.floor ((x - enemy_distance + ENEMY_SPACING_X ) / (ENEMY_R + ENEMY_SPACING_X));
var row = Math.floor (y / (ENEMY_R + ENEMY_SPACING_Y));
var enemyIndex = enemyToIndex(col, row);
if(enemy_grid[enemyIndex] == 1 && col < ENEMY_COLS && col >= 0) {
console.log(x, y, col, row, enemy_distance, enemyIndex);
enemy_grid[enemyIndex] = 0;
player_shot = false;
enemy_left -= 1;
if(enemy_left == 0) {
resetGame();
}
}
}
// 敵人是否擊中
enemyShootCheck = () => {
var distance = Math.sqrt(Math.pow(player_x - enemy_bullet_x, 2) + Math.pow((canvas.height - PLAYER_DIST_FROM_EDGE) - enemy_bullet_y, 2));
if(distance < PLAYER_R) {
chance -= 1;
enemy_shot = false;
if(chance < 0) {
resetGame();
}
}
}
resetGame = () => {
resetEnemy();
chance = 3;
}
// 移動敵人
moveEnemy = () => {
if(((ENEMY_R - ENEMY_SPACING_X * 2 + enemy_distance) <= 0) || ((ENEMY_R + ENEMY_SPACING_X) * ENEMY_COLS + enemy_distance >= canvas.width)) {
enemy_speed *= -1;
}
enemy_distance += enemy_speed;
}
// 敵人位置轉序列
enemyToIndex = (col, row) => {
return (col + ENEMY_COLS * row);
}
// 對應序列敵人存在
isEnemyExist = (col, row) => {
var enemy_index = enemyToIndex(col, row);
return (enemy_grid[enemy_index] == 1);
}
// 重置敵人數量
resetEnemy = () => {
enemy_left = 0;
for(var row = 0; row < ENEMY_ROWS; row++) {
for (var col = 0 ; col <ENEMY_COLS; col++) {
var enemy_index = enemyToIndex(col, row);
if (row > 1) {
enemy_grid[enemy_index] = 1;
enemy_left++;
} else {
enemy_grid[enemy_index] = 0;
}
}
}
}
// 顯示敵人
showEnemy = () => {
for(var col = 0; col < ENEMY_COLS; col++) {
for(var row = 0; row < ENEMY_ROWS; row++) {
if (isEnemyExist(col, row)) {
var enemy_x = col * (ENEMY_R + ENEMY_SPACING_X);
var enemy_y = row * (ENEMY_R + ENEMY_SPACING_Y);
drawCircle(enemy_x + enemy_distance, enemy_y, ENEMY_R, 'red');
}
}
}
}
// 矩形元件
drawRectangle = (topLeftX, topLeftY, boxWidth, boxHeight, color) => {
canvasContext.fillStyle = color;
canvasContext.fillRect(topLeftX, topLeftY, boxWidth, boxHeight);
}
// 圓形元件
drawCircle = (centerX, centerY, r, color) => {
canvasContext.fillStyle = color;
canvasContext.beginPath();
canvasContext.arc(centerX, centerY, r, 0, Math.PI * 2);
canvasContext.fill();
}
// 畫線
drawLine = (beginX, beginY, endX, endY, color) => {
canvasContext.strokeStyle = color;
canvasContext.beginPath();
canvasContext.moveTo(beginX, beginY);
canvasContext.lineTo(endX, endY);
canvasContext.stroke();
}
// 畫生命
drawLife = (lifeX, lifeY, size, color) => {
canvasContext.fillStyle = color;
canvasContext.beginPath();
canvasContext.arc(lifeX + size / 4, lifeY + size / 4, size / 4, Math.PI * 1, Math.PI * 0);
canvasContext.arc(lifeX + size * 3 / 4, lifeY + size / 4, size / 4, Math.PI * 1, Math.PI * 0);
canvasContext.moveTo(lifeX + size, lifeY + size / 4);
canvasContext.lineTo(lifeX + size / 2, lifeY + size);
canvasContext.lineTo(lifeX, lifeY + size / 4);
canvasContext.fill();
}
// 畫出生命
showLife = (num) => {
for (let life_count = 0; life_count < num; life_count++) {
drawLife(LIFE_SIZE * life_count, 0, LIFE_SIZE, 'red');
}
}
// 滑鼠點擊
mouseClick = (event) => {
playerShoot();
}
// 游標位置
mousePos = (event) => {
var rect = canvas.getBoundingClientRect();
var root = document.documentElement;
var mouse_x = event.clientX - rect.left - root.scrollLeft;
// 玩家X軸座標
player_x = mouse_x;
}
</script>
</body>
</html>